import { Controller, Get, Post, Body, Patch, Param, Delete, UseGuards, Logger, BadRequestException, Request } from '@nestjs/common';
import { JwtAuthGuard } from '../auth/jwt-auth.guard';
import { RolesGuard } from '../auth/roles.guard';
import { Roles } from '../auth/roles.decorator';
import { ExamService } from './exam.service';
import { Prisma, Exam } from '@prisma/client';
import { SubmitAnswerDto } from './dto/submit-answer.dto';

@Controller('exams')
@UseGuards(JwtAuthGuard, RolesGuard)
export class ExamController {
  private readonly logger = new Logger(ExamController.name);

  constructor(private readonly examService: ExamService) {}

  @Post()
  @Roles('TEACHER')
  async create(@Request() req, @Body() createExamDto: any): Promise<Exam> {
    this.logger.log(`创建新考试: ${createExamDto.title}`);
    this.logger.log(`TotalTotal: ${createExamDto.totalScore}`);
    this.logger.log(`Questions: ${JSON.stringify(createExamDto.questions)}`);
    try {
      // 验证必填字段
      if (!createExamDto.title || !createExamDto.subject || !createExamDto.startTime || !createExamDto.endTime) {
        throw new BadRequestException('缺少必填字段');
      }

      // 验证日期格式
      let startTime: Date;
      let endTime: Date;
      
      try {
        // 确保日期字符串是有效的ISO格式
        if (typeof createExamDto.startTime !== 'string' || typeof createExamDto.endTime !== 'string') {
          throw new Error('日期必须是字符串格式');
        }

        startTime = new Date(createExamDto.startTime);
        endTime = new Date(createExamDto.endTime);
        
        if (isNaN(startTime.getTime()) || isNaN(endTime.getTime())) {
          throw new Error('无效的日期格式，请使用ISO格式的日期字符串');
        }

        // 验证开始时间必须早于结束时间
        if (startTime >= endTime) {
          throw new Error('开始时间必须早于结束时间');
        }
      } catch (error) {
        throw new BadRequestException(error.message || '无效的日期格式');
      }

      // 验证用户ID
      if (!req.user?.id) {
        throw new BadRequestException('用户未登录或ID无效');
      }

      // 验证数值字段
      if (typeof createExamDto.duration !== 'number' || createExamDto.duration <= 0) {
        throw new BadRequestException('考试时长必须是大于0的数字');
      }
      if (typeof createExamDto.totalScore !== 'number' || createExamDto.totalScore <= 0) {
        throw new BadRequestException('总分必须是大于0的数字');
      }
      if (typeof createExamDto.passingScore !== 'number' || createExamDto.passingScore <= 0) {
        throw new BadRequestException('及格分数必须是大于0的数字');
      }
      if (createExamDto.passingScore > createExamDto.totalScore) {
        throw new BadRequestException('及格分数不能大于总分');
      }

      const examData = {
        title: createExamDto.title.trim(),
        subject: createExamDto.subject.trim(),
        description: createExamDto.description?.trim() || '',
        startTime,
        endTime,
        duration: createExamDto.duration,
        totalScore: createExamDto.totalScore,
        passingScore: createExamDto.passingScore,
        createdBy: {
          connect: { id: req.user.id }
        },
        questions: createExamDto.questions ? {
          connect: createExamDto.questions.map(q => ({ id: q.id }))
        } : undefined
      };
      return await this.examService.createExam(examData);
    } catch (error) {
      this.logger.error(`创建考试失败: ${error.message}`);
      throw new BadRequestException(error.message || '创建考试失败');
    }
  }

  @Get()
  async findAll(@Request() req): Promise<Exam[]> {
    this.logger.log('获取所有考试');
    try {
      return await this.examService.exams({});
    } catch (error) {
      this.logger.error(`获取考试列表失败: ${error.message}`);
      throw new BadRequestException('获取考试列表失败');
    }
  }

  @Get('available')
  @Roles('STUDENT')
  async getAvailableExams(@Request() req): Promise<any[]> {
    this.logger.log('获取可参加的考试列表');
    try {
      return await this.examService.getAvailableExamsWithStatus(req.user.id);
    } catch (error) {
      this.logger.error(`获取可参加考试列表失败: ${error.message}`);
      throw new BadRequestException(error.message || '获取可参加考试列表失败');
    }
  }

  @Get(':id')
  async findOne(@Param('id') id: string): Promise<Exam> {
    this.logger.log(`获取考试详情: ${id}`);
    try {
      const exam = await this.examService.exam({ id: Number(id) });
      if (!exam) {
        throw new BadRequestException('考试不存在');
      }
      return exam;
    } catch (error) {
      this.logger.error(`获取考试详情失败: ${error.message}`);
      throw new BadRequestException(error.message);
    }
  }

  @Patch(':id')
  async update(
    @Param('id') id: string,
    @Body() updateExamDto: Prisma.ExamUpdateInput,
  ): Promise<Exam> {
    this.logger.log(`更新考试: ${id}`);
    try {
      return await this.examService.updateExam({
        where: { id: Number(id) },
        data: updateExamDto,
      });
    } catch (error) {
      this.logger.error(`更新考试失败: ${error.message}`);
      throw new BadRequestException('更新考试失败');
    }
  }

  @Delete(':id')
  async remove(@Param('id') id: string): Promise<Exam> {
    this.logger.log(`删除考试: ${id}`);
    try {
      return await this.examService.deleteExam({ id: Number(id) });
    } catch (error) {
      this.logger.error(`删除考试失败: ${error.message}`);
      throw new BadRequestException('删除考试失败');
    }
  }

  @Get(':id/status')
  async getExamStatus(@Param('id') id: string): Promise<{ status: 'NOT_STARTED' | 'IN_PROGRESS' | 'ENDED' }> {
    this.logger.log(`获取考试状态: ${id}`);
    try {
      const status = await this.examService.getExamStatus(Number(id));
      return { status };
    } catch (error) {
      this.logger.error(`获取考试状态失败: ${error.message}`);
      throw new BadRequestException(error.message);
    }
  }

  @Post(':id/generate-questions')
  async generateRandomQuestions(
    @Param('id') id: string,
    @Body() params: { count: number; subject: string },
  ): Promise<Exam> {
    this.logger.log(`为考试 ${id} 生成随机题目`);
    try {
      return await this.examService.generateRandomQuestions({
        examId: Number(id),
        count: params.count,
        subject: params.subject,
      });
    } catch (error) {
      this.logger.error(`生成随机题目失败: ${error.message}`);
      throw new BadRequestException(error.message);
    }
  }

  @Get(':id/check-access')
  async checkExamAccess(
    @Param('id') id: string,
    @Request() req,
  ): Promise<{ canAccess: boolean }> {
    this.logger.log(`检查考试访问权限: ${id}`);
    try {
      const canAccess = await this.examService.checkExamAccess(
        Number(id),
        req.user.id,
      );
      return { canAccess };
    } catch (error) {
      this.logger.error(`检查考试访问权限失败: ${error.message}`);
      throw new BadRequestException(error.message);
    }
  }

  @Get(':id/details')
  @Roles('STUDENT')
  async getExamDetails(@Param('id') id: string, @Request() req): Promise<Exam> {
    this.logger.log(`获取考试详情: ${id}`);
    try {
      const examId = parseInt(id);
      if (isNaN(examId)) {
        throw new BadRequestException('无效的考试ID');
      }

      const exam = await this.examService.exam({ id: examId });
      if (!exam) {
        throw new BadRequestException('考试不存在');
      }

      const now = new Date();
      if (now < new Date(exam.startTime)) {
        throw new BadRequestException('考试还未开始');
      }
      if (now > new Date(exam.endTime)) {
        throw new BadRequestException('考试已结束');
      }

      return exam;
    } catch (error) {
      this.logger.error(`获取考试详情失败: ${error.message}`);
      throw new BadRequestException(error.message || '获取考试详情失败');
    }
  }

  @Get(':id/statistics')
  @Roles('TEACHER')
  async getExamStatistics(@Param('id') id: string): Promise<{
    scoreDistribution: { score: number; count: number }[];
    passRate: number;
    averageScore: number;
    totalStudents: number;
    highestScore: number;
    lowestScore: number;
  }> {
    this.logger.log(`获取考试统计数据: ${id}`);
    try {
      const examId = parseInt(id);
      if (isNaN(examId)) {
        throw new BadRequestException('无效的考试ID');
      }
      return await this.examService.getExamStatistics(examId);
    } catch (error) {
      this.logger.error(`获取考试统计数据失败: ${error.message}`);
      throw new BadRequestException(error.message || '获取考试统计数据失败');
    }
  }

  @Post(':id/submit')
  @Roles('STUDENT')
  async submitExam(
    @Param('id') id: string,
    @Request() req,
    @Body() submitAnswerDto: SubmitAnswerDto
  ): Promise<{ score: number }> {
    this.logger.log(`用户提交考试答案: ${id}`);
    try {
      const examId = parseInt(id);
      if (isNaN(examId)) {
        throw new BadRequestException('无效的考试ID');
      }

      if (!Array.isArray(submitAnswerDto.answers) || submitAnswerDto.answers.length === 0) {
        throw new BadRequestException('答案格式无效');
      }

      return await this.examService.submitExam(
        examId,
        req.user.id,
        submitAnswerDto.answers
      );
    } catch (error) {
      this.logger.error(`提交考试答案失败: ${error.message}`);
      throw new BadRequestException(error.message || '提交考试答案失败');
    }
  }

  @Get('student/results')
  @Roles('STUDENT')
  async getStudentResults(@Request() req) {
    this.logger.log(`获取学生 ${req.user.id} 的考试结果`);
    try {
      return await this.examService.getStudentResults(req.user.id);
    } catch (error) {
      this.logger.error(`获取学生考试结果失败: ${error.message}`);
      throw new BadRequestException(error.message || '获取考试结果失败');
    }
  }
}